#pragma once

#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<cstring>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstdlib>
#include<string>
#include<unistd.h>
#include<map>
class udpServer {
private:
    //服务器端口号
    int ser_prot;
    //socket文件描述符
    int sock;
    std::map<std::string,std::string> dict;
public:
    udpServer(int prot = 8080) :ser_prot(prot), sock(-1){
        dict.insert(std::pair<std::string,std::string>("apple","苹果"));
        dict.insert(std::pair<std::string,std::string>("banana","香蕉"));
        dict.insert(std::pair<std::string,std::string>("car","汽车"));
        dict.insert(std::pair<std::string,std::string>("sun","☀"));
        dict.insert(std::pair<std::string,std::string>("moon","🌙"));
        dict.insert(std::pair<std::string,std::string>("star","⭐"));
    }
    void initServe() {
        //创建socket文件描述符
        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock < 0) {
            std::cerr << "sock error!" << std::endl;
        }
        struct sockaddr_in local;
        local.sin_family = AF_INET;         //使用IPV4
        local.sin_port = htons(ser_prot);   //prot主机序列转为网络序列
        local.sin_addr.s_addr = INADDR_ANY; //IP赋值本地的任意IP地址
        socklen_t len = sizeof(local);

        //绑定端口号
        //将sockaddr_in类型的参数强转位sockaddr才能传入bind
        if (bind(sock, (struct sockaddr*)&local, len) < 0) {
            std::cerr << "bind error!" << std::endl;
            exit(1);
        }

    }
    void start() {
        std::cout<<"Server start"<<std::endl;
        char msg[64];
        while (true) {
            msg[0] = '\0';
            struct sockaddr_in end_point;
            socklen_t len = sizeof(end_point);
            //接收对端发来的信息
            ssize_t s = recvfrom(sock,msg,sizeof(msg)-1,0,(struct sockaddr*)&end_point,&len);
            if(s > 0){
                msg[s] = '\0';
                std::cout<<"client #"<<"["<<inet_ntoa(end_point.sin_addr)<<" :"<<ntohs(end_point.sin_port)<<"] "<<msg<<std::endl;
                std::string echo ="unknow";
                auto it = dict.find(msg);
                if(it != dict.end()){
                    echo = dict[msg];
                }   
                //服务器向客户端回显信息
                sendto(sock,echo.c_str(),echo.size(),0,(struct sockaddr*)&end_point,len);
            }
        }
    }
    ~udpServer() {
        close(sock);
    }
};

